package alkaid.eis.schedule.core;

import static org.springframework.util.StringUtils.hasText;

import java.lang.reflect.Method;

import org.springframework.util.ReflectionUtils;

import alkaid.eis.common.util.ExceptionHelper;
import alkaid.eis.common.util.Timer;
import alkaid.eis.schedule.domain.JobInfoRepository;
import alkaid.eis.schedule.domain.JobLog.Level;
import alkaid.eis.schedule.domain.JobService;
import alkaid.eis.schedule.util.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 定时任务
 * 
 * @author Lucky Yang
 * @since 0.0.1
 */
@Slf4j
public class SchedulingTask implements Runnable {
    public final Long jobInfoId;
    public final JobService jobService;
    public final JobInfoRepository jobInfoRepository;

    private static long counter = 0;
    public final long id = counter++;

    public SchedulingTask(Long jobInfoId, JobService jobService, JobInfoRepository jobInfoRepository) {
        this.jobInfoId = jobInfoId;
        this.jobService = jobService;
        this.jobInfoRepository = jobInfoRepository;
    }

    @Override
    public void run() {
        jobInfoRepository.findById(jobInfoId).ifPresentOrElse(jobInfo -> {
            Timer timer = new Timer();
            try {
                jobService.createLog(jobInfo, Level.RUNNING, formatMessage("开始执行任务"));

                final String className = jobInfo.getClassName();
                final String methodName = jobInfo.getMethodName();
                final String methodParams = jobInfo.getMethodParams();

                Object target = SpringContextUtils.getBean(Class.forName(className));
                Method method = null;
                if (hasText(methodParams)) {
                    method = target.getClass().getDeclaredMethod(methodName, String.class);
                } else {
                    method = target.getClass().getDeclaredMethod(methodName);
                }

                ReflectionUtils.makeAccessible(method);
                if (hasText(methodParams)) {
                    method.invoke(target, methodParams);
                } else {
                    method.invoke(target);
                }
                jobService.createLog(jobInfo, Level.COMPLETE, formatMessage("任务执行结束"), timer.duration());
            } catch (Exception e) {
                jobService.createLog(jobInfo, Level.ERROR, formatMessage(ExceptionHelper.stacktraceToString(e)),
                        timer.duration());
            }
        }, () -> log.warn("JobInfo does not exist: [jobInfoId={}, taskId={}]", jobInfoId, id));

    }

    public String formatMessage(String message) {
        return String.format("[%s]%s", String.valueOf(id), message);
    }
}
